﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;

namespace CalcSharp.Core.Containers
{
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public class UserFunction
    {
        public int reqparams;
        public string code;

        public UserFunction(string code, int param)
        {
            this.code = code;
            this.reqparams = param;
        }
    }

    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public class FunctData
    {
        public string desc;
        public UserFunction value;
    }

    public class FunctionManager : IMemMan<FunctData, UserFunction>
    {
        private Dictionary<string, UserFunction> Engine;

        public FunctionManager()
        {
            this.Engine = new Dictionary<string, UserFunction>();
        }

        public int Count
        {
            get { return this.Engine.Keys.Count; }
        }

        public void Clear()
        {
            this.Engine.Clear();
        }

        public bool isset(string name)
        {
            return Engine.ContainsKey(name.ToLower());
        }

        public void unset(string name)
        {
            Engine.Remove(name.ToLower());
        }

        public int Add(FunctData item)
        {
            if (Engine.ContainsKey(item.desc)) Engine[item.desc] = item.value;
            else Engine.Add(item.desc, item.value);
            return Engine.Count;
        }

        /// <summary>
        /// Packs a single variable for serializazion
        /// </summary>
        /// <param name="index">the variable's name</param>
        /// <returns>the packed variable</returns>
        public FunctData PackSingle(string name)
        {
            if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name can't be null");
            name = name.ToLower();
            FunctData ret = new FunctData();
            ret.value = Engine[name];
            ret.desc = name;
            return ret;
        }


        public string[] keys
        {
            get { return Engine.Keys.ToArray(); }
        }

        public UserFunction this[string s]
        {
            get
            {
                s = s.ToLower(CultureInfo.CurrentCulture);
                if (this.Engine.ContainsKey(s)) return Engine[s];
                else throw new CSException("Function does not exist: " + s);
            }
            set
            {
                s = s.ToLower(CultureInfo.CurrentCulture);
                if (this.Engine.ContainsKey(s)) this.Engine[s] = value;
                else this.Engine.Add(s, value);
            }
        }
    }
}
